#include "../cgdb/include/def.h"
#include "../cgdb/include/Window.h"
#include "../cgdb/include/Layout.h"
#include "../cgdb/include/Sources.h"

enum WINS_{
    FILES,
    SRC,
    DBG,
    THREADS,
    CALL_STACK,
    MEM,
    STACK,
    TTY,
    GDB,
    ALL_TYPE
};

int main(int c, char** args)
{
    /* Uncomment to debug and attach */
#if 1
        int t;
            read (0, &t, 1);
#endif

    int ch;

    initscr();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);
    start_color();
    mvprintw(0, 0, "q - For exit");
    {    
        Sources win[ALL_TYPE];
        HLayout layout;
        HLayout h_code_layout;
        HLayout h_thr_call_layout;
        HLayout h_mem_layout;

        VLayout v_code_layout;
        VLayout v_thr_call_layout;
        VLayout v_mem_layout;
        VLayout v_tty_layout;
        VLayout v_gdb_layout;

        layout.Locate(0,0, LINES, COLS);
        layout.Enable();
        h_code_layout.Enable();
        h_thr_call_layout.Enable();
        h_mem_layout.Enable();
        v_code_layout.Enable();
        v_thr_call_layout.Enable();
        v_mem_layout.Enable();
        v_tty_layout.Enable();
        v_gdb_layout.Enable();

        layout.AddWindow(&win[FILES]);

        h_code_layout.AddWindow(&win[SRC]);
        h_code_layout.AddWindow(&win[DBG]);
        v_code_layout.AddWindow(&h_code_layout);
        
        h_thr_call_layout.AddWindow(&win[THREADS]);
        h_thr_call_layout.AddWindow(&win[CALL_STACK]);
        v_thr_call_layout.AddWindow(&h_thr_call_layout);


        h_mem_layout.AddWindow(&win[MEM]);
        h_mem_layout.AddWindow(&win[STACK]);
        v_mem_layout.AddWindow(&h_mem_layout);

        v_tty_layout.AddWindow(&win[TTY]);

        v_gdb_layout.AddWindow(&win[GDB]);

        v_tty_layout.AddWindow(&v_gdb_layout);
        v_mem_layout.AddWindow(&v_tty_layout);
        v_thr_call_layout.AddWindow(&v_mem_layout);
        v_code_layout.AddWindow(&v_thr_call_layout);
        layout.AddWindow(&v_code_layout);


        int curr_win = 0;
        for (int i = 0; i < ALL_TYPE; i++) {
            win[i].Enable();
            win[i].Paint();
        }

        while((ch = getch()) != 'q')
        {   
            switch(ch)
            {
                case KEY_DOWN:
                    layout.Move(0, 1);
                    break;
                case KEY_UP:
                    layout.Move(0, -1);
                    break;
                case KEY_LEFT:
                    layout.Move(-1, 0);
                    break;
                case KEY_RIGHT:
                    layout.Move(1, 0);
                    break;
                case 's':
                    layout.Resize_RB(0, 1);
                    break;
                case 'w':
                    layout.Resize_RB(0, -1);
                    break;
                case 'a':
                    layout.Resize_RB(-1, 0);
                    break;
                case 'd':
                    layout.Resize_RB(1, 0);
                    break;
                case 'S':
                    layout.Resize_LT(0, 1);
                    break;
                case 'W':
                    layout.Resize_LT(0, -1);
                    break;
                case 'A':
                    layout.Resize_LT(-1, 0);
                    break;
                case 'D':
                    layout.Resize_LT(1, 0);
                    break;
                case '9':
                    if(curr_win == FILES)
                        layout.Shift(-1);
                    if(curr_win == SRC || curr_win == DBG )
                        h_code_layout.Shift(-1);
                    if(curr_win == THREADS || curr_win == CALL_STACK )
                        h_thr_call_layout.Shift(-1);
                    if(curr_win == MEM || curr_win == STACK)
                        h_mem_layout.Shift(-1);
                    break;
                case '0':
                    if(curr_win == FILES)
                        layout.Shift(1);
                    if(curr_win == SRC || curr_win == DBG )
                        h_code_layout.Shift(1);
                    if(curr_win == THREADS || curr_win == CALL_STACK )
                        h_thr_call_layout.Shift(1);
                    if(curr_win == MEM || curr_win == STACK)
                        h_mem_layout.Shift(1);
                    break;
                case '-':
                    if(curr_win == SRC || curr_win == DBG )
                        v_code_layout.Shift(-1);
                    if(curr_win == THREADS || curr_win == CALL_STACK )
                        v_thr_call_layout.Shift(-1);
                    if(curr_win == MEM || curr_win == STACK)
                        v_mem_layout.Shift(-1);
                    break;
                case '=':
                    if(curr_win == SRC || curr_win == DBG )
                        v_code_layout.Shift(1);
                    if(curr_win == THREADS || curr_win == CALL_STACK )
                        v_thr_call_layout.Shift(1);
                    if(curr_win == MEM || curr_win == STACK)
                        v_mem_layout.Shift(1);
                    break;
                case 't':
                    if(win[curr_win].IsEnabled())
                        win[curr_win].Disable();
                    else
                        win[curr_win].Enable();
                    break;
                case '\t':
                    curr_win++;
                    if(curr_win >= ALL_TYPE){
                        curr_win = 0;
                    }
                    win[curr_win].SetCurrent();
                    break;
            }
            win[curr_win].Paint();
        }
    }
    endwin();
    return 0;    
}

